

/*
 * @Author       : DonnieLiang
 * @Date         : 2024-11-22
 * @Version      : 1.0
 * @Description  : gw_ktj_client_app.c
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>


#include <memory.h> /*使用memcpy所需的头文件*/

#include <time.h>

#include <sys/types.h>
#include <sys/socket.h>


#include <netdb.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>




 #include <pthread.h>  

#include "iotv30_config.h"
#include "rtc_calendar.h"
//#include  "iotv30_config.h"
#include  "gw_ktj_api_config.h"


#include "gui_cjson_api.h"
#include "gui_logist.h"
//#include "tcp_api_01.h" 


#include "gw_ktj_tcp_client.h" 


 
 
 //TCP Client 测试全局状态标记变量
 //bit7:0,没有数据要发送;1,有数据要发送 
 //bit6:0,没有收到数据;1,收到数据了.
 //bit5:0,没有连接上服务器;1,连接上服务器了.
 //bit4~0:保留

  
 static tcp_client_flag_u	tcp_client_flag ;
 static uint8_t             ucTcp_ClientStep = 0;	


void gw_ktj_Tcp_Client_Init(void)
{

  tcp_client_flag.all = 0;
  ucTcp_ClientStep    = 0;	
	
}



//返回值 0---链接断开，  1---链接成功
 uint8_t gw_ktj_IsTcpClientConnected( void )
{
    return tcp_client_flag.bit.link;
}



void gw_ktj_TCP_Reset( void )
{
  tcp_client_flag.bit.reset = 1;	
 // tcp_client_flag.bit.link  = 0;

}





//---------主进程---------------------
 uint16_t gw_ktj_Tcp_Client_App_Process(ClientInfo_st*	 pinfo)
{	

	 switch( ucTcp_ClientStep ) 													
	 {

			case 0:  // 	case SOCK_CLOSED:			  //socket处于关闭状态
			{								
					 //if( 0 != IsEth_LinkDone( ) ) 

					 if ( tcp_client_connect(pinfo ) > 0 )  //  tcp_connect()
					 {						  
						  tcp_client_flag.bit.link  = 1;
						  printf("gw_ktj tcp connect ok: socket_fd= %d\n\r", pinfo->fd );	
						  printf("gw_ktj tcp_client_flag.bit.link = %d\n\r", tcp_client_flag.bit.link );		
						  ucTcp_ClientStep++;

						  return 1;//创建线程

					 }else{  //无法连接----1sec 后再重新链接

					     /*usleep函数将该进程挂起一定时间，单位微秒，头文件unistd.h*/
					    // usleep(100000);
						 sleep(1);   //感觉这里的延迟不起作用    

					 }
							
							
			} break;
					
						
			case 1:  // 创建接收线程	
			{							
			    ucTcp_ClientStep++;
			} break;
			
					
		  case 2:  // 	
		  {								

		        if( 0 == tcp_client_flag.bit.link  ) 
				{ //链接已经断开	

				     printf("gw_ktj socket close\n\r");
					 printf("gw_ktj tcp_client_flag.bit.link=%d\n\r", tcp_client_flag.bit.link);

					 
					 ucTcp_ClientStep = 0; //重新建立链接	
					
				}else if( 0 != tcp_client_flag.bit.reset )
				{ //主动断开链接	
									
				   tcp_client_flag.bit.reset = 0;	
				   tcp_client_flag.bit.link  = 0;
				
				   ucTcp_ClientStep = 0; //重新建立链接						
									
				}else{ //正常链接----发送数据给服务器 
					
#if 0 //ver.1.45

					if( 0 != Tcp_TxData[TCP_API_CH_LOCAL].Flag )//是否有数据需要发送
					{					
						
                         //发送数据，最后一个参数为 0 时，可以用 write() 替代（ send 等同于 write ）						
								//write(pinfo->fd, Tcp_TxData[TCP_API_CH_LOCAL].Buff , Tcp_TxData[TCP_API_CH_LOCAL].Len );		
								ret = send(pinfo->fd, Tcp_TxData[TCP_API_CH_LOCAL].Buff , Tcp_TxData[TCP_API_CH_LOCAL].Len , 0 );
				
								if ( ret != Tcp_TxData[TCP_API_CH_LOCAL].Len  )
								{
									  printf("gw_ktj server offline ret=%d,len=%d\n\r",ret,Tcp_TxData[TCP_API_CH_LOCAL].Len ); 

									  close(pinfo->fd);
									
									  ucTcp_ClientStep = 0; //重新建立链接																	
								}else{
									 printf("gw_ktj socket send done\n\r");
								}
												
						 Tcp_TxData[TCP_API_CH_LOCAL].Len = 0;
						 Tcp_TxData[TCP_API_CH_LOCAL].Flag = 0;
					}

			  
#endif

				}
				
																											
		}break; 				
				
		
				
		default:
		{				
			ucTcp_ClientStep = 0 ;		
			
		}break; 			
			
				
	}  // switch( ucTcp_ClientStep )	

	 
 return 0;//不需要创建线程	

	
} 




 
 ///----------------接收进程-----------------------

 
  /***********************************************
  函数名：Tcp_Client_RecvProcess
  功能：负责监测接收来自服务器的数据  
  参数：sockfd -- 套接字描述符
  输出：把收到的socket数据保存，并传给上级
 
  返回值：null
  *************************************************/
  void gw_ktj_Tcp_Client_RecvProcess(int *sockfd)
  {
	  int connfd = *sockfd;
	  ssize_t  nRead;
  
	 //  LOG_NAME(); 
	  printf("%s 子线程ID: %ld\n\r",__FUNCTION__, pthread_self());
 
	  while(1)
	  {
	  
		  /*接收服务器发来的消息*/
		  nRead = recv(connfd , Tcp_RxData[TCP_API_CH_LOCAL].Buff , TCP_CLIENT_RX_BUFSIZE , 0);
		  
		  /*recv函数返回值: <0 出错	;=0 链接关闭  ;>0接收到的字节数 */
		  if(nRead <= 0)
		  {//服务器已经不在线
			  
			  RTC_Prinft_Now( );	
			  if(nRead == 0)
			  {
				printf("local_ktj_js server offline!nRead=%zd\n\r", nRead);   
			  }else{
				printf("local_ktj_js server error!nRead=%zd\n\r", nRead);   
			  }

		      Tcp_RxData[TCP_API_CH_LOCAL].Len = 0;
			  close(connfd);
			  *sockfd = -1;
			  tcp_client_flag.bit.link	= 0;
			  pthread_exit(0); //退出当前线程
			  //exit(0);
			 
		  }else{

			 Tcp_RxData[TCP_API_CH_LOCAL].Len = nRead;

#if  DEBUG_PRINT_ENABLE // DEBUG_PRINT_ENABLE  		-----------打印字符串格式-------
			RTC_Prinft_Now( );					   
			logout( " ETH_%d local_ktj_js Rx: len=%d\n",TCP_API_CH_LOCAL, Tcp_RxData[TCP_API_CH_LOCAL].Len );

			if(Tcp_RxData[TCP_API_CH_LOCAL].Len <1024 )
			{
                printf("%s\n",Tcp_RxData[TCP_API_CH_LOCAL].Buff );
			}else{
				
#if  LARGE_PRINT_ENABLE 				
                printf("%s\n",Tcp_RxData[TCP_API_CH_LOCAL].Buff);    ///just for testing
                printf("large data end\n");  				
#else	
				//printf("%128s\n",Tcp_RxData[TCP_API_CH_LOCAL].Buff);
			    printf("data too much,print omit...!\n");   
#endif	


			}

#endif	


#if 0  //  DEBUG_PRINT_ENABLE  		----------打印16进制格式-------
										   
					RTC_Prinft_Now( );					   
					logout( " ETH_%d CH_IOTV30 Rx:\n",TCP_API_CH_IOTV30);					
					UartPrintHex2String( Tcp_RxData[TCP_API_CH_LOCAL].Buff , Tcp_RxData[TCP_API_CH_LOCAL].Len);  
					UartPrintString( "\n\r"); 


//					UartPrintString( "\n\r cmd =	");
//					UartPrintHex2String( &Tcp_RxData[TCP_API_CH_IOTV30].Buff[10], 1);	
//			 ETH Rx: 
//68 00 14 00 00 07 80 68 80 02 f0 01 de 16 		

#endif	


	  //以太网接收没有用链表缓存----需要改进  
 
           json_cmd_decode( (const char *)Tcp_RxData[TCP_API_CH_LOCAL].Buff );
           memset(Tcp_RxData[TCP_API_CH_LOCAL].Buff, 0, Tcp_RxData[TCP_API_CH_LOCAL].Len);
           Tcp_RxData[TCP_API_CH_LOCAL].Len = 0;

		}


         //usleep(13000);
 		//sleep(5);
 
	  /*usleep函数将该进程挂起一定时间，单位微秒，头文件unistd.h*/
	  // usleep(100000);

   }//while	  
 
 	  
}
 
 


// 获取本机mac
int get_local_mac(const char *eth_inf, char *mac_str,uint8_t *mac_int)
{
    struct ifreq ifr;  // 非 -std=c99  版本
    int sd;

    bzero(&ifr, sizeof(struct ifreq));
    if( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("get %s mac address socket creat error\n", eth_inf);
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, sizeof(ifr.ifr_name) - 1);

    if(ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    {
        printf("get %s mac address error\n", eth_inf);
        close(sd);
        return -1;
    }

    snprintf(mac_str, LOCAL_MAC_STR_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
        (unsigned char)ifr.ifr_hwaddr.sa_data[0],
        (unsigned char)ifr.ifr_hwaddr.sa_data[1],
        (unsigned char)ifr.ifr_hwaddr.sa_data[2],
        (unsigned char)ifr.ifr_hwaddr.sa_data[3],
        (unsigned char)ifr.ifr_hwaddr.sa_data[4],
        (unsigned char)ifr.ifr_hwaddr.sa_data[5]);

     memcpy( mac_int,ifr.ifr_hwaddr.sa_data,6);

    close(sd);

    return 0;
}


#define   IFNAMSIZ	  IF_NAMESIZE

// 获取本机ip
int get_local_ip(const char *eth_inf, char *ip_str,uint8_t *ip_int)
{
    int sd;
    struct sockaddr_in sin;
    struct ifreq ifr;

    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sd)
    {
        printf("socket error: %s\n", strerror(errno));
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;

    // if error: No such device
    if (ioctl(sd, SIOCGIFADDR, &ifr) < 0)
    {
        printf("ioctl error: %s\n", strerror(errno));
        close(sd);
        return -1;
    }

    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    snprintf(ip_str, LOCAL_IP_STR_SIZE, "%s", inet_ntoa(sin.sin_addr));

   ip_int[0] = sin.sin_addr.s_addr>>24 ;
   ip_int[1] = sin.sin_addr.s_addr>>16 ;
   ip_int[2] = sin.sin_addr.s_addr>>8 ;
   ip_int[3] = sin.sin_addr.s_addr &0x0000FF;


    close(sd);

    return 0;

}











